﻿using System;
using System.Data;
using System.Reflection;
using System.Runtime.Serialization;
using System.Web;
using System.Web.Services;
using System.Web.SessionState;
using FancyIdea.PingShui.Core.Util;
using System.Xml;
using System.Text;
using FancyIdea.PingShui.Core.Dal;

namespace FancyIdea.PingShui.Core
{
    public class HttpHandler : IHttpHandler, IRequiresSessionState
    {
        private const string DefaultActionKey = "fi_act";
        private const string DefaultUrlKey = "fi_url";

        private const BindingFlags DefaultBindingFlags
            = BindingFlags.IgnoreCase | BindingFlags.Instance
            | BindingFlags.NonPublic | BindingFlags.Public;
        private readonly Type[] NoParameterTypes = new Type[0];
        private readonly ParameterModifier[] NoParameterModifiers
             = new ParameterModifier[0];

        #region 工具
        protected string GetStringValue(string key)
        {
            return Request[key];
        }

        protected string[] GetStringsValue(string key)
        {
            try
            {
                return Request[key].Split(',');
            }
            catch
            {
                return null;
            }
        }

        protected int GetInt32Value(string key)
        {
            return StringParser.ToInt32(Request[key], -1);
        }

        protected int[] GetIntValue(string key)
        {
            string[] keys = Request[key].Split(',');
            if (keys == null || keys.Length < 1)
            {
                return null;
            }
            int[] k = new int[keys.Length];
            for (int i = 0; i < k.Length; i++)
            {
                k[i] = int.Parse(keys[i]);
            }
            return k;
        }

        protected bool GetBooleanValue(string key)
        {
            return StringParser.ToBoolean(Request[key]);
        }

        protected DateTime GetDateTimeValue(string key)
        {
            try
            {
                return DateTime.Parse(Request[key]);
            }
            catch (Exception)
            {
                return DateTime.MinValue;
            }
        }

        protected float GetFloatValue(string key)
        {
            try
            {
                return float.Parse(Request[key]);
            }
            catch (Exception)
            {
                return 0;
            }
        }

        protected decimal GetDecimalValue(string key)
        {
            try
            {
                return Convert.ToDecimal(Request[key]);
            }
            catch (Exception)
            {
                return -1;
            }
        }

        protected long GetInt64Value(string key)
        {
            return StringParser.ToInt64(Request[key], -1);
        }

        protected long GetInt64Value(string key, int fromBase)
        {
            try
            {
                return Convert.ToInt64(Request[key], fromBase);
            }
            catch (Exception)
            {
                return -1;
            }
        }
        #endregion

        #region Web相关对象
        protected HttpContext Context
        {
            get;
            private set;
        }

        protected HttpRequest Request
        {
            get;
            private set;
        }

        protected HttpResponse Response
        {
            get;
            private set;
        }

        protected HttpSessionState Session
        {
            get;
            private set;
        }

        protected HttpServerUtility Server
        {
            get;
            private set;
        }

        protected string Action
        {
            get;
            private set;
        }

        protected string UrlReffer
        {
            get;
            private set;
        }

        protected string UrlNext
        {
            get;
            private set;
        }

        protected long UserId
        {
            get;
            private set;
        }
        #endregion

        #region 反馈输出
        protected void ResponseJavascript()
        {
            Response.ContentType = "text/javascript";
        }

        protected void ResponsePlainText()
        {
            Response.ContentType = "text/plain";
        }

        protected void ResponseHtml()
        {
            Response.ContentType = "text/html";
        }

        protected void ResponseJson(object jsonObject)
        {
            ResponseJavascript();
            if (jsonObject == null)
            {
                return;
            }
        }


        #endregion

        public virtual void ProcessRequest(HttpContext context)
        {
            Context = context;
            Request = context.Request;
            Response = context.Response;
            Session = context.Session;
            Server = context.Server;

            UrlReffer = Request.UrlReferrer == null ? null
                : Request.UrlReferrer.ToString();

            long? userId = Session["userid"] as long?;
            UserId = userId == null ? -1L : userId.Value;

            PreParseArguments();
            Handle();
        }

        protected virtual void Handle()
        {
            if (string.IsNullOrEmpty(Action))
            {
                HandleNullAction();
                return;
            }

            MethodInfo method = GetType().GetMethod(Action, DefaultBindingFlags,
                null, NoParameterTypes, NoParameterModifiers);

            if (method == null)
            {
                HandleNotFoundAction();
                return;
            }

            try
            {
                method.Invoke(this, null);
            }
            catch (TargetInvocationException e)
            {
                if (e.InnerException != null)
                {
                    WriteReturnXml(-1, e.InnerException.Message, null);
                }
                else
                {
                    WriteReturnXml(-1, e.Message, null);
                }
            }
            catch (Exception ex)
            {
                WriteReturnXml(-1, ex.Message, null);
            }
        }

        protected virtual void HandleNullAction()
        {
            // TODO 改为Exception
            Response.StatusCode = 403;
            Response.End();
        }

        protected virtual void HandleNotFoundAction()
        {
            throw new InvalidOperationException("不认识的命令: " + Action);
        }

        protected virtual void PreParseArguments()
        {
            Action = Request[DefaultActionKey];
            UrlNext = Request[DefaultUrlKey];
        }

        public virtual bool IsReusable
        {
            get
            {
                return false;
            }
        }

        public class HttpHandlerException : Exception
        {
            public object Result
            {
                get;
                private set;
            }

            public HttpHandlerException()
            {
            }

            public HttpHandlerException(object result)
            {
                Result = result;
            }
        }

        protected bool CheckPower(string 权限)
        {
            string 税务人员代码 = Session["username"] == null ?
                "" : Session["username"].ToString();
            return 税务机关和人员操作.CheckPower(税务人员代码, 权限);
        }

        protected void WriteReturnXml(int code, string message, DataTable table)
        {
            XmlTextWriter writer = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;  //缩进格式
            writer.Indentation = 4;
            writer.WriteStartDocument();
            writer.WriteStartElement("response");

            writer.WriteElementString("code", code.ToString());
            writer.WriteElementString("message", message);
            writer.WriteStartElement("datas");
            if (table != null && table.Rows.Count > 0)
            {
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    writer.WriteStartElement("data");
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        writer.WriteElementString(table.Columns[j].ColumnName, table.Rows[i][j].ToString());
                    }
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }

        protected void WriteReturnXml(int code, string message, DataRow row, DataTable table)
        {
            XmlTextWriter writer = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;  //缩进格式
            writer.Indentation = 4;
            writer.WriteStartDocument();
            writer.WriteStartElement("response");

            writer.WriteElementString("code", code.ToString());
            writer.WriteElementString("message", message);
            writer.WriteStartElement("datas");
            if (row != null)
            {
                writer.WriteStartElement("data");
                for (int k = 0; k < row.Table.Columns.Count; k++)
                {
                    writer.WriteElementString(row.Table.Columns[k].ColumnName, row.Table.Rows[0][k].ToString());
                }
                if (table != null && table.Rows.Count > 0)
                {
                    writer.WriteStartElement("sub_datas");
                    for (int i = 0; i < table.Rows.Count; i++)
                    {
                        writer.WriteStartElement("sub_data");
                        for (int j = 0; j < table.Columns.Count; j++)
                        {
                            writer.WriteElementString(table.Columns[j].ColumnName, table.Rows[i][j].ToString());
                        }
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }

        protected void WriteListXml(int code, string message,
            int count, int perPage, int total, int page,
            DataTable table)
        {
            XmlTextWriter writer = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;  //缩进格式
            writer.Indentation = 4;
            writer.WriteStartDocument();
            writer.WriteStartElement("response");
            writer.WriteElementString("code", code.ToString());
            writer.WriteElementString("message", message);

            writer.WriteStartElement("data");
            writer.WriteElementString("count", count.ToString());
            writer.WriteStartElement("page_info");
            writer.WriteElementString("per_page", perPage.ToString());
            writer.WriteElementString("total", total.ToString());
            writer.WriteElementString("page", page.ToString());
            writer.WriteEndElement();
            writer.WriteStartElement("datas");
            if (table != null && table.Rows.Count > 0)
            {
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    writer.WriteStartElement("data");
                    for (int j = 0; j < table.Columns.Count; j++)
                    {
                        writer.WriteElementString(table.Columns[j].ColumnName, table.Rows[i][j].ToString());
                    }
                    writer.WriteEndElement();
                }
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }
    }
}